home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / GAS_1_38.ARJ / EXPR.C < prev    next >
C/C++ Source or Header  |  1991-01-28  |  30KB  |  981 lines

  1. /* expr.c -operands, expressions-
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * This is really a branch office of as-read.c. I split it out to clearly
  22.  * distinguish the world of expressions from the world of statements.
  23.  * (It also gives smaller files to re-compile.)
  24.  * Here, "operand"s are of expressions, not instructions.
  25.  */
  26.  
  27. #include <ctype.h>
  28. #include "as.h"
  29. #include "flonum.h"
  30. #include "read.h"
  31. #include "struc-symbol.h"
  32. #include "expr.h"
  33. #include "obstack.h"
  34. #include "symbols.h"
  35.  
  36. static void clean_up_expression();    /* Internal. */
  37. extern const char EXP_CHARS[];    /* JF hide MD floating pt stuff all the same place */
  38. extern const char FLT_CHARS[];
  39.  
  40. #ifdef SUN_ASM_SYNTAX
  41. extern int local_label_defined[];
  42. #endif
  43.  
  44. /*
  45.  * Build any floating-point literal here.
  46.  * Also build any bignum literal here.
  47.  */
  48.  
  49. /* LITTLENUM_TYPE    generic_buffer [6];    /* JF this is a hack */
  50. /* Seems atof_machine can backscan through generic_bignum and hit whatever
  51.    happens to be loaded before it in memory.  And its way too complicated
  52.    for me to fix right.  Thus a hack.  JF:  Just make generic_bignum bigger,
  53.    and never write into the early words, thus they'll always be zero.
  54.    I hate Dean's floating-point code.  Bleh.
  55.  */
  56. LITTLENUM_TYPE    generic_bignum [SIZE_OF_LARGE_NUMBER+6];
  57. FLONUM_TYPE    generic_floating_point_number =
  58. {
  59.   & generic_bignum [6],        /* low (JF: Was 0) */
  60.   & generic_bignum [SIZE_OF_LARGE_NUMBER+6 - 1], /* high JF: (added +6) */
  61.   0,                /* leader */
  62.   0,                /* exponent */
  63.   0                /* sign */
  64. };
  65. /* If nonzero, we've been asked to assemble nan, +inf or -inf */
  66. int generic_floating_point_magic;
  67.  
  68. /*
  69.  * Summary of operand().
  70.  *
  71.  * in:    Input_line_pointer points to 1st char of operand, which may
  72.  *    be a space.
  73.  *
  74.  * out:    A expressionS. X_seg determines how to understand the rest of the
  75.  *    expressionS.
  76.  *    The operand may have been empty: in this case X_seg == SEG_NONE.
  77.  *    Input_line_pointer -> (next non-blank) char after operand.
  78.  *
  79.  */
  80.  
  81. static segT
  82. operand (expressionP)
  83.      register expressionS *    expressionP;
  84. {
  85.   register char        c;
  86.   register char *name;    /* points to name of symbol */
  87.   register struct symbol *    symbolP; /* Points to symbol */
  88.  
  89.   extern  char hex_value[];    /* In hex_value.c */
  90.   char    *local_label_name();
  91.  
  92.   SKIP_WHITESPACE();        /* Leading whitespace is part of operand. */
  93.   c = * input_line_pointer ++;    /* Input_line_pointer -> past char in c. */
  94.   if (isdigit(c))
  95.     {
  96.       register valueT    number;    /* offset or (absolute) value */
  97.       register short int digit;    /* value of next digit in current radix */
  98.                 /* invented for humans only, hope */
  99.                 /* optimising compiler flushes it! */
  100.       register short int radix;    /* 8, 10 or 16 */
  101.                 /* 0 means we saw start of a floating- */
  102.                 /* point constant. */
  103.       register short int maxdig;/* Highest permitted digit value. */
  104.       register int    too_many_digits; /* If we see >= this number of */
  105.                 /* digits, assume it is a bignum. */
  106.       register char *    digit_2; /* -> 2nd digit of number. */
  107.                int    small;    /* TRUE if fits in 32 bits. */
  108.  
  109.       if (c=='0')
  110.     {            /* non-decimal radix */
  111.       if ((c = * input_line_pointer ++)=='x' || c=='X')
  112.         {
  113.           c = * input_line_pointer ++; /* read past "0x" or "0X" */
  114.           maxdig = radix = 16;
  115.           too_many_digits = 9;
  116.         }
  117.       else
  118.         {
  119.           /* If it says '0f' and the line ends or it DOESN'T look like
  120.              a floating point #, its a local label ref.  DTRT */
  121.           if(c=='f' && (! *input_line_pointer ||
  122.                 (!index("+-.0123456789",*input_line_pointer) &&
  123.                  !index(EXP_CHARS,*input_line_pointer))))
  124.         {
  125.               maxdig = radix = 10;
  126.           too_many_digits = 11;
  127.           c='0';
  128.           input_line_pointer-=2;
  129.         }
  130.           else if (c && index (FLT_CHARS,c))
  131.         {
  132.           radix = 0;    /* Start of floating-point constant. */
  133.                 /* input_line_pointer -> 1st char of number. */
  134.           expressionP -> X_add_number =  - (isupper(c) ? tolower(c) : c);
  135.         }
  136.           else
  137.         {        /* By elimination, assume octal radix. */
  138.           radix = 8;
  139.           maxdig = 10;    /* Un*x sux. Compatibility. */
  140.           too_many_digits = 11;
  141.         }
  142.         }
  143.       /* c == char after "0" or "0x" or "0X" or "0e" etc.*/
  144.     }
  145.       else
  146.     {
  147.       maxdig = radix = 10;
  148.       too_many_digits = 11;
  149.     }
  150.       if (radix)
  151.     {            /* Fixed-point integer constant. */
  152.                 /* May be bignum, or may fit in 32 bits. */
  153. /*
  154.  * Most numbers fit into 32 bits, and we want this case to be fast.
  155.  * So we pretend it will fit into 32 bits. If, after making up a 32
  156.  * bit number, we realise that we have scanned more digits than
  157.  * comfortably fit into 32 bits, we re-scan the digits coding
  158.  * them into a bignum. For decimal and octal numbers we are conservative: some
  159.  * numbers may be assumed bignums when in fact they do fit into 32 bits.
  160.  * Numbers of any radix can have excess leading zeros: we strive
  161.  * to recognise this and cast them back into 32 bits.
  162.  * We must check that the bignum really is more than 32
  163.  * bits, and change it back to a 32-bit number if it fits.
  164.  * The number we are looking for is expected to be positive, but
  165.  * if it fits into 32 bits as an unsigned number, we let it be a 32-bit
  166.  * number. The cavalier approach is for speed in ordinary cases.
  167.  */
  168.       digit_2 = input_line_pointer;
  169.       for (number=0;  (digit=hex_value[c])<maxdig;  c = * input_line_pointer ++)
  170.         {
  171.           number = number * radix + digit;
  172.         }
  173.       /* C contains character after number. */
  174.       /* Input_line_pointer -> char after C. */
  175.       small = input_line_pointer - digit_2 < too_many_digits;
  176.       if ( ! small)
  177.         {
  178.           /*
  179.            * We saw a lot of digits. Manufacture a bignum the hard way.
  180.            */
  181.           LITTLENUM_TYPE *    leader;    /* -> high order littlenum of the bignum. */
  182.           LITTLENUM_TYPE *    pointer; /* -> littlenum we are frobbing now. */
  183.           long int        carry;
  184.  
  185.           leader = generic_bignum;
  186.           generic_bignum [0] = 0;
  187.           generic_bignum [1] = 0;
  188.                 /* We could just use digit_2, but lets be mnemonic. */
  189.           input_line_pointer = -- digit_2; /* -> 1st digit. */
  190.           c = *input_line_pointer ++;
  191.           for (;   (carry = hex_value [c]) < maxdig;   c = * input_line_pointer ++)
  192.         {
  193.           for (pointer = generic_bignum;
  194.                pointer <= leader;
  195.                pointer ++)
  196.             {
  197.               long int    work;
  198.  
  199.               work = carry + radix * * pointer;
  200.               * pointer = work & LITTLENUM_MASK;
  201.               carry = work >> LITTLENUM_NUMBER_OF_BITS;
  202.             }
  203.           if (carry)
  204.             {
  205.               if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
  206.             {    /* Room to grow a longer bignum. */
  207.               * ++ leader = carry;
  208.             }
  209.             }
  210.         }
  211.           /* Again, C is char after number, */
  212.           /* input_line_pointer -> after C. */
  213.           know( BITS_PER_INT == 32 );
  214.           know( LITTLENUM_NUMBER_OF_BITS == 16 );
  215.           /* Hence the constant "2" in the next line. */
  216.           if (leader < generic_bignum + 2)
  217.         {        /* Will fit into 32 bits. */
  218.           number =
  219.             ( (generic_bignum [1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS )
  220.             | (generic_bignum [0] & LITTLENUM_MASK);
  221.           small = TRUE;
  222.         }
  223.           else
  224.         {
  225.           number = leader - generic_bignum + 1;    /* Number of littlenums in the bignum. */
  226.         }
  227.         }
  228.       if (small)
  229.         {
  230.           /*
  231.            * Here with number, in correct radix. c is the next char.
  232.            * Note that unlike Un*x, we allow "011f" "0x9f" to
  233.            * both mean the same as the (conventional) "9f". This is simply easier
  234.            * than checking for strict canonical form. Syntax sux!
  235.            */
  236.           if (number<10)
  237.         {
  238. #ifdef SUN_ASM_SYNTAX
  239.           if (c=='b' || (c=='$' && local_label_defined[number]))
  240. #else
  241.           if (c=='b')
  242. #endif
  243.             {
  244.               /*
  245.                * Backward ref to local label.
  246.                * Because it is backward, expect it to be DEFINED.
  247.                */
  248.               /*
  249.                * Construct a local label.
  250.                */
  251.               name = local_label_name ((int)number, 0);
  252.               if ( (symbolP = symbol_table_lookup(name)) /* seen before */
  253.               && (symbolP -> sy_type & N_TYPE) != N_UNDF /* symbol is defined: OK */
  254.               )
  255.             {        /* Expected path: symbol defined. */
  256.               /* Local labels are never absolute. Don't waste time checking absoluteness. */
  257.               know(   (symbolP -> sy_type & N_TYPE) == N_DATA
  258.                    || (symbolP -> sy_type & N_TYPE) == N_TEXT );
  259.               expressionP -> X_add_symbol = symbolP;
  260.               expressionP -> X_add_number = 0;
  261.               expressionP -> X_seg          = N_TYPE_seg [symbolP -> sy_type];
  262.             }
  263.               else
  264.             {        /* Either not seen or not defined. */
  265.               as_warn( "Backw. ref to unknown label \"%d:\", 0 assumed.",
  266.                   number
  267.                   );
  268.               expressionP -> X_add_number = 0;
  269.               expressionP -> X_seg        = SEG_ABSOLUTE;
  270.             }
  271.             }
  272.           else
  273.             {
  274. #ifdef SUN_ASM_SYNTAX
  275.               if (c=='f' || (c=='$' && !local_label_defined[number]))
  276. #else
  277.               if (c=='f')
  278. #endif
  279.             {
  280.               /*
  281.                * Forward reference. Expect symbol to be undefined or
  282.                * unknown. Undefined: seen it before. Unknown: never seen
  283.                * it in this pass.
  284.                * Construct a local label name, then an undefined symbol.
  285.                * Don't create a XSEG frag for it: caller may do that.
  286.                * Just return it as never seen before.
  287.                */
  288.               name = local_label_name ((int)number, 1);
  289.               if ( symbolP = symbol_table_lookup( name ))
  290.                 {
  291.                   /* We have no need to check symbol properties. */
  292.                   know(   (symbolP -> sy_type & N_TYPE) == N_UNDF
  293.                    || (symbolP -> sy_type & N_TYPE) == N_DATA
  294.                    || (symbolP -> sy_type & N_TYPE) == N_TEXT);
  295.                 }
  296.               else
  297.                 {
  298.                   symbolP = symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
  299.                   symbol_table_insert (symbolP);
  300.                 }
  301.               expressionP -> X_add_symbol      = symbolP;
  302.               expressionP -> X_seg             = SEG_UNKNOWN;
  303.               expressionP -> X_subtract_symbol = NULL;
  304.               expressionP -> X_add_number      = 0;
  305.             }
  306.               else
  307.             {        /* Really a number, not a local label. */
  308.               expressionP -> X_add_number = number;
  309.               expressionP -> X_seg        = SEG_ABSOLUTE;
  310.               input_line_pointer --; /* Restore following character. */
  311.             }        /* if (c=='f') */
  312.             }            /* if (c=='b') */
  313.         }
  314.           else
  315.         {            /* Really a number. */
  316.           expressionP -> X_add_number = number;
  317.           expressionP -> X_seg        = SEG_ABSOLUTE;
  318.           input_line_pointer --; /* Restore following character. */
  319.         }            /* if (number<10) */
  320.         }
  321.       else
  322.         {
  323.           expressionP -> X_add_number = number;
  324.           expressionP -> X_seg = SEG_BIG;
  325.           input_line_pointer --; /* -> char following number. */
  326.         }            /* if (small) */
  327.     }            /* (If integer constant) */
  328.       else
  329.     {            /* input_line_pointer -> */
  330.                 /* floating-point constant. */
  331.       int error_code;
  332.  
  333.       error_code = atof_generic
  334.         (& input_line_pointer, ".", EXP_CHARS,
  335.          & generic_floating_point_number);
  336.  
  337.       if (error_code)
  338.         {
  339.           if (error_code == ERROR_EXPONENT_OVERFLOW)
  340.         {
  341.           as_warn( "Bad floating-point constant: exponent overflow, probably assembling junk" );
  342.         }
  343.           else
  344.         {          
  345.           as_warn( "Bad floating-point constant: unknown error code=%d.", error_code);
  346.         }
  347.         }
  348.       expressionP -> X_seg = SEG_BIG;
  349.                 /* input_line_pointer -> just after constant, */
  350.                 /* which may point to whitespace. */
  351.       know( expressionP -> X_add_number < 0 ); /* < 0 means "floating point". */
  352.     }            /* if (not floating-point constant) */
  353.     }
  354.   else if(c=='.' && !is_part_of_name(*input_line_pointer)) {
  355.     extern struct obstack frags;
  356.  
  357.     /*
  358.        JF:  '.' is pseudo symbol with value of current location in current
  359.        segment. . .
  360.      */
  361.     symbolP = symbol_new("L0\001",
  362.              (unsigned char)(seg_N_TYPE[(int)now_seg]),
  363.              0,
  364.              0,
  365.              (valueT)(obstack_next_free(&frags)-frag_now->fr_literal),
  366.              frag_now);
  367.     expressionP->X_add_number=0;
  368.     expressionP->X_add_symbol=symbolP;
  369.     expressionP->X_seg = now_seg;
  370.  
  371.   } else if ( is_name_beginner(c) ) /* here if did not begin with a digit */
  372.     {
  373.       /*
  374.        * Identifier begins here.
  375.        * This is kludged for speed, so code is repeated.
  376.        */
  377.       name =  -- input_line_pointer;
  378.       c = get_symbol_end();
  379.       symbolP = symbol_table_lookup(name);
  380.       if (symbolP)
  381.         {
  382.           /*
  383.            * If we have an absolute symbol, then we know it's value now.
  384.            */
  385.           register segT        seg;
  386.  
  387.           seg = N_TYPE_seg [(int) symbolP -> sy_type & N_TYPE];
  388.           if ((expressionP -> X_seg = seg) == SEG_ABSOLUTE )
  389.         {
  390.           expressionP -> X_add_number = symbolP -> sy_value;
  391.         }
  392.       else
  393.         {
  394.           expressionP -> X_add_number  = 0;
  395.           expressionP -> X_add_symbol  = symbolP;
  396.         }
  397.     }
  398.       else
  399.     {
  400.       expressionP -> X_add_symbol
  401.         = symbolP
  402.         = symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
  403.  
  404.       expressionP -> X_add_number  = 0;
  405.       expressionP -> X_seg         = SEG_UNKNOWN;
  406.       symbol_table_insert (symbolP);
  407.     }
  408.       * input_line_pointer = c;
  409.       expressionP -> X_subtract_symbol = NULL;
  410.     }
  411.   else if (c=='(')/* didn't begin with digit & not a name */
  412.     {
  413.       (void)expression( expressionP );
  414.       /* Expression() will pass trailing whitespace */
  415.       if ( * input_line_pointer ++ != ')' )
  416.     {
  417.       as_warn( "Missing ')' assumed");
  418.       input_line_pointer --;
  419.     }
  420.       /* here with input_line_pointer -> char after "(...)" */
  421.     }
  422.   else if ( c=='~' || c=='-' )
  423.     {        /* unary operator: hope for SEG_ABSOLUTE */
  424.       switch(operand (expressionP)) {
  425.       case SEG_ABSOLUTE:
  426.             /* input_line_pointer -> char after operand */
  427.     if ( c=='-' )
  428.       {
  429.         expressionP -> X_add_number = - expressionP -> X_add_number;
  430. /*
  431.  * Notice: '-' may  overflow: no warning is given. This is compatible
  432.  * with other people's assemblers. Sigh.
  433.  */
  434.       }
  435.     else
  436.       {
  437.         expressionP -> X_add_number = ~ expressionP -> X_add_number;
  438.       }
  439.       break;
  440.  
  441.       case SEG_TEXT:
  442.       case SEG_DATA:
  443.       case SEG_BSS:
  444.       case SEG_PASS1:
  445.       case SEG_UNKNOWN:
  446.     if(c=='-') {        /* JF I hope this hack works */
  447.       expressionP->X_subtract_symbol=expressionP->X_add_symbol;
  448.       expressionP->X_add_symbol=0;
  449.       expressionP->X_seg=SEG_DIFFERENCE;
  450.       break;
  451.     }
  452.       default:        /* unary on non-absolute is unsuported */
  453.     as_warn("Unary operator %c ignored because bad operand follows", c);
  454.     break;
  455.     /* Expression undisturbed from operand(). */
  456.       }
  457.     }
  458.   else if (c=='\'')
  459.     {
  460. /*
  461.  * Warning: to conform to other people's assemblers NO ESCAPEMENT is permitted
  462.  * for a single quote. The next character, parity errors and all, is taken
  463.  * as the value of the operand. VERY KINKY.
  464.  */
  465.       expressionP -> X_add_number = * input_line_pointer ++;
  466.       expressionP -> X_seg        = SEG_ABSOLUTE;
  467.     }
  468.   else
  469.     {
  470.               /* can't imagine any other kind of operand */
  471.       expressionP -> X_seg = SEG_NONE;
  472.       input_line_pointer --;
  473.     }
  474. /*
  475.  * It is more 'efficient' to clean up the expressions when they are created.
  476.  * Doing it here saves lines of code.
  477.  */
  478.   clean_up_expression (expressionP);
  479.   SKIP_WHITESPACE();        /* -> 1st char after operand. */
  480.   know( * input_line_pointer != ' ' );
  481.   return (expressionP -> X_seg);
  482. }                /* operand */
  483.  
  484. /* Internal. Simplify a struct expression for use by expr() */
  485.  
  486. /*
  487.  * In:    address of a expressionS.
  488.  *    The X_seg field of the expressionS may only take certain values.
  489.  *    Now, we permit SEG_PASS1 to make code smaller & faster.
  490.  *    Elsewise we waste time special-case testing. Sigh. Ditto SEG_NONE.
  491.  * Out:    expressionS may have been modified:
  492.  *    'foo-foo' symbol references cancelled to 0,
  493.  *        which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
  494.  *    Unused fields zeroed to help expr().
  495.  */
  496.  
  497. static void
  498. clean_up_expression (expressionP)
  499.      register expressionS * expressionP;
  500. {
  501.   switch (expressionP -> X_seg)
  502.     {
  503.     case SEG_NONE:
  504.     case SEG_PASS1:
  505.       expressionP -> X_add_symbol    = NULL;
  506.       expressionP -> X_subtract_symbol    = NULL;
  507.       expressionP -> X_add_number    = 0;
  508.       break;
  509.  
  510.     case SEG_BIG:
  511.     case SEG_ABSOLUTE:
  512.       expressionP -> X_subtract_symbol    = NULL;
  513.       expressionP -> X_add_symbol    = NULL;
  514.       break;
  515.  
  516.     case SEG_TEXT:
  517.     case SEG_DATA:
  518.     case SEG_BSS:
  519.     case SEG_UNKNOWN:
  520.       expressionP -> X_subtract_symbol    = NULL;
  521.       break;
  522.  
  523.     case SEG_DIFFERENCE:
  524.       /*
  525.        * It does not hurt to 'cancel' NULL==NULL
  526.        * when comparing symbols for 'eq'ness.
  527.        * It is faster to re-cancel them to NULL
  528.        * than to check for this special case.
  529.        */
  530.       if (expressionP -> X_subtract_symbol == expressionP -> X_add_symbol
  531.           || (   expressionP->X_subtract_symbol
  532.           && expressionP->X_add_symbol
  533.             && expressionP->X_subtract_symbol->sy_frag==expressionP->X_add_symbol->sy_frag
  534.           && expressionP->X_subtract_symbol->sy_value==expressionP->X_add_symbol->sy_value))
  535.     {
  536.       expressionP -> X_subtract_symbol    = NULL;
  537.       expressionP -> X_add_symbol        = NULL;
  538.       expressionP -> X_seg            = SEG_ABSOLUTE;
  539.     }
  540.       break;
  541.  
  542.     default:
  543.       BAD_CASE( expressionP -> X_seg);
  544.       break;
  545.     }
  546. }
  547.  
  548. /*
  549.  *            expr_part ()
  550.  *
  551.  * Internal. Made a function because this code is used in 2 places.
  552.  * Generate error or correct X_?????_symbol of expressionS.
  553.  */
  554.  
  555. /*
  556.  * symbol_1 += symbol_2 ... well ... sort of.
  557.  */
  558.  
  559. static segT
  560. expr_part (symbol_1_PP, symbol_2_P)
  561.      struct symbol **    symbol_1_PP;
  562.      struct symbol *    symbol_2_P;
  563. {
  564.   segT            return_value;
  565.  
  566.   know(    (* symbol_1_PP)                   == NULL
  567.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_TEXT
  568.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_DATA
  569.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_BSS
  570.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF
  571.        );
  572.   know(      symbol_2_P             == NULL
  573.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_TEXT
  574.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_DATA
  575.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_BSS
  576.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_UNDF
  577.        );
  578.   if (* symbol_1_PP)
  579.     {
  580.       if (((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
  581.     {
  582.       if (symbol_2_P)
  583.         {
  584.           return_value = SEG_PASS1;
  585.           * symbol_1_PP = NULL;
  586.         }
  587.       else
  588.         {
  589.           know( ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
  590.           return_value = SEG_UNKNOWN;
  591.         }
  592.     }
  593.       else
  594.     {
  595.       if (symbol_2_P)
  596.         {
  597.           if ((symbol_2_P -> sy_type & N_TYPE) == N_UNDF)
  598.         {
  599.           * symbol_1_PP = NULL;
  600.           return_value = SEG_PASS1;
  601.         }
  602.           else
  603.         {
  604.           /* {seg1} - {seg2} */
  605.           as_warn( "Expression too complex, 2 symbols forgotten: \"%s\" \"%s\"",
  606.               (* symbol_1_PP) -> sy_name, symbol_2_P -> sy_name );
  607.           * symbol_1_PP = NULL;
  608.           return_value = SEG_ABSOLUTE;
  609.         }
  610.         }
  611.       else
  612.         {
  613.           return_value = N_TYPE_seg [(* symbol_1_PP) -> sy_type & N_TYPE];
  614.         }
  615.     }
  616.     }
  617.   else
  618.     {                /* (* symbol_1_PP) == NULL */
  619.       if (symbol_2_P)
  620.     {
  621.       * symbol_1_PP = symbol_2_P;
  622.       return_value = N_TYPE_seg [(symbol_2_P) -> sy_type & N_TYPE];
  623.     }
  624.       else
  625.     {
  626.       * symbol_1_PP = NULL;
  627.       return_value = SEG_ABSOLUTE;
  628.     }
  629.     }
  630.   know(   return_value == SEG_ABSOLUTE            
  631.        || return_value == SEG_TEXT            
  632.        || return_value == SEG_DATA            
  633.        || return_value == SEG_BSS            
  634.        || return_value == SEG_UNKNOWN            
  635.        || return_value == SEG_PASS1            
  636.        );
  637.   know(   (* symbol_1_PP) == NULL                
  638.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == seg_N_TYPE [(int) return_value] );
  639.   return (return_value);
  640. }                /* expr_part() */
  641.  
  642. /* Expression parser. */
  643.  
  644. /*
  645.  * We allow an empty expression, and just assume (absolute,0) silently.
  646.  * Unary operators and parenthetical expressions are treated as operands.
  647.  * As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
  648.  *
  649.  * We used to do a aho/ullman shift-reduce parser, but the logic got so
  650.  * warped that I flushed it and wrote a recursive-descent parser instead.
  651.  * Now things are stable, would anybody like to write a fast parser?
  652.  * Most expressions are either register (which does not even reach here)
  653.  * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
  654.  * So I guess it doesn't really matter how inefficient more complex expressions
  655.  * are parsed.
  656.  *
  657.  * After expr(RANK,resultP) input_line_pointer -> operator of rank <= RANK.
  658.  * Also, we have consumed any leading or trailing spaces (operand does that)
  659.  * and done all intervening operators.
  660.  */
  661.  
  662. typedef enum
  663. {
  664. O_illegal,            /* (0)  what we get for illegal op */
  665.  
  666. O_multiply,            /* (1)  * */
  667. O_divide,            /* (2)  / */
  668. O_modulus,            /* (3)  % */
  669. O_left_shift,            /* (4)  < */
  670. O_right_shift,            /* (5)  > */
  671. O_bit_inclusive_or,        /* (6)  | */
  672. O_bit_or_not,            /* (7)  ! */
  673. O_bit_exclusive_or,        /* (8)  ^ */
  674. O_bit_and,            /* (9)  & */
  675. O_add,                /* (10) + */
  676. O_subtract            /* (11) - */
  677. }
  678. operatorT;
  679.  
  680. #define __ O_illegal
  681.  
  682. static const operatorT op_encoding [256] = {    /* maps ASCII -> operators */
  683.  
  684. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  685. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  686.  
  687. __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
  688. __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
  689. __, __, __, __, __, __, __, __,
  690. __, __, __, __, O_left_shift, __, O_right_shift, __,
  691. __, __, __, __, __, __, __, __,
  692. __, __, __, __, __, __, __, __,
  693. __, __, __, __, __, __, __, __,
  694. __, __, __, __, __, __, O_bit_exclusive_or, __,
  695. __, __, __, __, __, __, __, __,
  696. __, __, __, __, __, __, __, __,
  697. __, __, __, __, __, __, __, __,
  698. __, __, __, __, O_bit_inclusive_or, __, __, __,
  699.  
  700. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  701. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  702. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  703. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  704. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  705. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  706. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  707. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
  708. };
  709.  
  710.  
  711. /*
  712.  *    Rank    Examples
  713.  *    0    operand, (expression)
  714.  *    1    + -
  715.  *    2    & ^ ! |
  716.  *    3    * / % < >
  717.  */
  718. typedef char operator_rankT;
  719. static const operator_rankT
  720. op_rank [] = { 0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1 };
  721.  
  722. segT                /* Return resultP -> X_seg. */
  723. expr (rank, resultP)
  724.      register operator_rankT    rank; /* Larger # is higher rank. */
  725.      register expressionS *    resultP; /* Deliver result here. */
  726. {
  727.   expressionS        right;
  728.   register operatorT    op_left;
  729.   register char        c_left;    /* 1st operator character. */
  730.   register operatorT    op_right;
  731.   register char        c_right;
  732.  
  733.   know( rank >= 0 );
  734.   (void)operand (resultP);
  735.   know( * input_line_pointer != ' ' ); /* Operand() gobbles spaces. */
  736.   c_left = * input_line_pointer; /* Potential operator character. */
  737.   op_left = op_encoding [c_left];
  738.   while (op_left != O_illegal && op_rank [(int) op_left] > rank)
  739.     {
  740.       input_line_pointer ++;    /* -> after 1st character of operator. */
  741.                 /* Operators "<<" and ">>" have 2 characters. */
  742.       if (* input_line_pointer == c_left && (c_left == '<' || c_left == '>') )
  743.     {
  744.       input_line_pointer ++;
  745.     }            /* -> after operator. */
  746.       if (SEG_NONE == expr (op_rank[(int) op_left], &right))
  747.     {
  748.       as_warn("Missing operand value assumed absolute 0.");
  749.       resultP -> X_add_number    = 0;
  750.       resultP -> X_subtract_symbol    = NULL;
  751.       resultP -> X_add_symbol    = NULL;
  752.       resultP -> X_seg = SEG_ABSOLUTE;
  753.     }
  754.       know( * input_line_pointer != ' ' );
  755.       c_right = * input_line_pointer;
  756.       op_right = op_encoding [c_right];
  757.       if (* input_line_pointer == c_right && (c_right == '<' || c_right == '>') )
  758.     {
  759.       input_line_pointer ++;
  760.     }            /* -> after operator. */
  761.       know(   (int) op_right == 0
  762.        || op_rank [(int) op_right] <= op_rank[(int) op_left] );
  763.       /* input_line_pointer -> after right-hand quantity. */
  764.       /* left-hand quantity in resultP */
  765.       /* right-hand quantity in right. */
  766.       /* operator in op_left. */
  767.       if ( resultP -> X_seg == SEG_PASS1 || right . X_seg == SEG_PASS1 )
  768.     {
  769.       resultP -> X_seg = SEG_PASS1;
  770.     }
  771.       else
  772.     {
  773.       if ( resultP -> X_seg == SEG_BIG )
  774.         {
  775.           as_warn( "Left operand of %c is a %s.  Integer 0 assumed.",
  776.               c_left, resultP -> X_add_number > 0 ? "bignum" : "float");
  777.           resultP -> X_seg = SEG_ABSOLUTE;
  778.           resultP -> X_add_symbol = 0;
  779.           resultP -> X_subtract_symbol = 0;
  780.           resultP -> X_add_number = 0;
  781.         }
  782.       if ( right . X_seg == SEG_BIG )
  783.         {
  784.           as_warn( "Right operand of %c is a %s.  Integer 0 assumed.",
  785.               c_left, right . X_add_number > 0 ? "bignum" : "float");
  786.           right . X_seg = SEG_ABSOLUTE;
  787.           right . X_add_symbol = 0;
  788.           right . X_subtract_symbol = 0;
  789.           right . X_add_number = 0;
  790.         }
  791.       if ( op_left == O_subtract )
  792.         {
  793.           /*
  794.            * Convert - into + by exchanging symbols and negating number.
  795.            * I know -infinity can't be negated in 2's complement:
  796.            * but then it can't be subtracted either. This trick
  797.            * does not cause any further inaccuracy.
  798.            */
  799.  
  800.           register struct symbol *    symbolP;
  801.  
  802.           right . X_add_number      = - right . X_add_number;
  803.           symbolP                   = right . X_add_symbol;
  804.           right . X_add_symbol    = right . X_subtract_symbol;
  805.           right . X_subtract_symbol = symbolP;
  806.           if (symbolP)
  807.         {
  808.           right . X_seg        = SEG_DIFFERENCE;
  809.         }
  810.           op_left = O_add;
  811.         }
  812.  
  813.       if ( op_left == O_add )
  814.         {
  815.           segT    seg1;
  816.           segT    seg2;
  817.           
  818.           know(   resultP -> X_seg == SEG_DATA        
  819.            || resultP -> X_seg == SEG_TEXT        
  820.            || resultP -> X_seg == SEG_BSS        
  821.            || resultP -> X_seg == SEG_UNKNOWN        
  822.            || resultP -> X_seg == SEG_DIFFERENCE    
  823.            || resultP -> X_seg == SEG_ABSOLUTE        
  824.            || resultP -> X_seg == SEG_PASS1        
  825.            );
  826.           know(     right .  X_seg == SEG_DATA        
  827.            ||   right .  X_seg == SEG_TEXT        
  828.            ||   right .  X_seg == SEG_BSS        
  829.            ||   right .  X_seg == SEG_UNKNOWN        
  830.            ||   right .  X_seg == SEG_DIFFERENCE    
  831.            ||   right .  X_seg == SEG_ABSOLUTE        
  832.            ||   right .  X_seg == SEG_PASS1        
  833.            );
  834.           
  835.           clean_up_expression (& right);
  836.           clean_up_expression (resultP);
  837.  
  838.           seg1 = expr_part (& resultP -> X_add_symbol, right . X_add_symbol);
  839.           seg2 = expr_part (& resultP -> X_subtract_symbol, right . X_subtract_symbol);
  840.           if (seg1 == SEG_PASS1 || seg2 == SEG_PASS1) {
  841.           need_pass_2 = TRUE;
  842.           resultP -> X_seg = SEG_PASS1;
  843.           } else if (seg2 == SEG_ABSOLUTE)
  844.           resultP -> X_seg = seg1;
  845.           else if (   seg1 != SEG_UNKNOWN
  846.             && seg1 != SEG_ABSOLUTE
  847.             && seg2 != SEG_UNKNOWN
  848.             && seg1 != seg2) {
  849.           know( seg2 != SEG_ABSOLUTE );
  850.           know( resultP -> X_subtract_symbol );
  851.  
  852.           know( seg1 == SEG_TEXT || seg1 == SEG_DATA || seg1== SEG_BSS );
  853.           know( seg2 == SEG_TEXT || seg2 == SEG_DATA || seg2== SEG_BSS );
  854.           know( resultP -> X_add_symbol      );
  855.           know( resultP -> X_subtract_symbol );
  856.           as_warn("Expression too complex: forgetting %s - %s",
  857.               resultP -> X_add_symbol      -> sy_name,
  858.               resultP -> X_subtract_symbol -> sy_name);
  859.           resultP -> X_seg = SEG_ABSOLUTE;
  860.           /* Clean_up_expression() will do the rest. */
  861.         } else
  862.           resultP -> X_seg = SEG_DIFFERENCE;
  863.  
  864.           resultP -> X_add_number += right . X_add_number;
  865.           clean_up_expression (resultP);
  866.         }
  867.       else
  868.         {            /* Not +. */
  869.           if ( resultP -> X_seg == SEG_UNKNOWN || right . X_seg == SEG_UNKNOWN )
  870.         {
  871.           resultP -> X_seg = SEG_PASS1;
  872.           need_pass_2 = TRUE;
  873.         }
  874.           else
  875.         {
  876.           resultP -> X_subtract_symbol = NULL;
  877.           resultP -> X_add_symbol = NULL;
  878.           /* Will be SEG_ABSOLUTE. */
  879.           if ( resultP -> X_seg != SEG_ABSOLUTE || right . X_seg != SEG_ABSOLUTE )
  880.             {
  881.               as_warn( "Relocation error. Absolute 0 assumed.");
  882.               resultP -> X_seg        = SEG_ABSOLUTE;
  883.               resultP -> X_add_number = 0;
  884.             }
  885.           else
  886.             {
  887.               switch ( op_left )
  888.             {
  889.             case O_bit_inclusive_or:
  890.               resultP -> X_add_number |= right . X_add_number;
  891.               break;
  892.               
  893.             case O_modulus:
  894.               if (right . X_add_number)
  895.                 {
  896.                   resultP -> X_add_number %= right . X_add_number;
  897.                 }
  898.               else
  899.                 {
  900.                   as_warn( "Division by 0. 0 assumed." );
  901.                   resultP -> X_add_number = 0;
  902.                 }
  903.               break;
  904.               
  905.             case O_bit_and:
  906.               resultP -> X_add_number &= right . X_add_number;
  907.               break;
  908.               
  909.             case O_multiply:
  910.               resultP -> X_add_number *= right . X_add_number;
  911.               break;
  912.               
  913.             case O_divide:
  914.               if (right . X_add_number)
  915.                 {
  916.                   resultP -> X_add_number /= right . X_add_number;
  917.                 }
  918.               else
  919.                 {
  920.                   as_warn( "Division by 0. 0 assumed." );
  921.                   resultP -> X_add_number = 0;
  922.                 }
  923.               break;
  924.               
  925.             case O_left_shift:
  926.               resultP -> X_add_number <<= right . X_add_number;
  927.               break;
  928.               
  929.             case O_right_shift:
  930.               resultP -> X_add_number >>= right . X_add_number;
  931.               break;
  932.               
  933.             case O_bit_exclusive_or:
  934.               resultP -> X_add_number ^= right . X_add_number;
  935.               break;
  936.               
  937.             case O_bit_or_not:
  938.               resultP -> X_add_number |= ~ right . X_add_number;
  939.               break;
  940.               
  941.             default:
  942.               BAD_CASE( op_left );
  943.               break;
  944.             } /* switch(operator) */
  945.             }
  946.         }        /* If we have to force need_pass_2. */
  947.         }            /* If operator was +. */
  948.     }            /* If we didn't set need_pass_2. */
  949.       op_left = op_right;
  950.     }                /* While next operator is >= this rank. */
  951.   return (resultP -> X_seg);
  952. }
  953.  
  954. /*
  955.  *            get_symbol_end()
  956.  *
  957.  * This lives here because it belongs equally in expr.c & read.c.
  958.  * Expr.c is just a branch office read.c anyway, and putting it
  959.  * here lessens the crowd at read.c.
  960.  *
  961.  * Assume input_line_pointer is at start of symbol name.
  962.  * Advance input_line_pointer past symbol name.
  963.  * Turn that character into a '\0', returning its former value.
  964.  * This allows a string compare (RMS wants symbol names to be strings)
  965.  * of the symbol name.
  966.  * There will always be a char following symbol name, because all good
  967.  * lines end in end-of-line.
  968.  */
  969. char
  970. get_symbol_end()
  971. {
  972.   register char c;
  973.  
  974.   while ( is_part_of_name( c = * input_line_pointer ++ ) )
  975.     ;
  976.   * -- input_line_pointer = 0;
  977.   return (c);
  978. }
  979.  
  980. /* end: expr.c */
  981.